package io.gitee.kotle.android.adapter

import android.graphics.drawable.GradientDrawable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.ColorInt
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.paging.*
import androidx.recyclerview.widget.*
import androidx.viewbinding.ViewBinding
import io.gitee.kotle.android.utils.asOrNull
import io.gitee.kotle.android.adapter.decoration.LinearLayoutManagerDivider
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers


/**
 * 创建适配器
 * 有大量数据，而且数据多变，建议优先使用[RecyclerViewListAdapter]
 */
fun <Data> recyclerViewAdapter(
    areItemTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否是同一组数据*/,
    areContentsTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否内容相同*/
) = RecyclerViewAdapter<Data>(areItemTheSame, areContentsTheSame)


/**
 * 创建适配器
 * 少量数据或者设置完数据后不会发生变化，建议优先使用[RecyclerViewAdapter]
 */
fun <Data> recyclerViewListAdapter(
    areItemTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否是同一组数据*/,
    areContentsTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否内容相同*/
) = RecyclerViewListAdapter<Data>(areItemTheSame, areContentsTheSame)

/**
 * 创建适配器
 * 有大量数据，而且数据多变，建议优先使用[RecyclerViewListAdapter]
 */
fun <Data, Holder : RecyclerViewHolder<Data, *>> recyclerViewAdapter(
    holder: Class<Holder>,
    areItemTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否是同一组数据*/,
    areContentsTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否内容相同*/
): RecyclerViewAdapter<Data> {
    val adapter = RecyclerViewAdapter<Data>(areItemTheSame, areContentsTheSame)
    adapter.register(holder)
    return adapter
}

/**
 * 创建适配器
 *  少量数据或者设置完数据后不会发生变化，建议优先使用[RecyclerViewAdapter]
 *
 */
fun <Data, Holder : RecyclerViewHolder<Data, *>> recyclerViewListAdapter(
    holder: Class<Holder>,
    areItemTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否是同一组数据*/,
    areContentsTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否内容相同*/
): RecyclerViewListAdapter<Data> {
    val adapter = RecyclerViewListAdapter<Data>(areItemTheSame, areContentsTheSame)
    adapter.register(holder)
    return adapter
}

fun <Data : Any, Holder : RecyclerViewHolder<Data, *>> recyclerViewPagingAdapter(
    holder: Class<Holder>,
    areItemTheSame: ((old: Data?, new: Data?) -> Boolean)? = null,/*是否是同一组数据*/
    areContentsTheSame: ((old: Data?, new: Data?) -> Boolean)? = null,/*是否内容相同*/
    mainDispatcher: CoroutineDispatcher = Dispatchers.Main.immediate,
    workerDispatcher: CoroutineDispatcher = Dispatchers.Default,
): RecyclerViewPagingAdapter<Data> {
    val adapter =
        RecyclerViewPagingAdapter(
            areItemTheSame,
            areContentsTheSame,
            mainDispatcher,
            workerDispatcher
        )
    adapter.register(holder)
    return adapter
}

/**
 * 创建适配器
 */
fun <Data : Any> recyclerViewPagingAdapter(
    areItemTheSame: ((old: Data?, new: Data?) -> Boolean)? = null,/*是否是同一组数据*/
    areContentsTheSame: ((old: Data?, new: Data?) -> Boolean)? = null,/*是否内容相同*/
    mainDispatcher: CoroutineDispatcher = Dispatchers.Main.immediate,
    workerDispatcher: CoroutineDispatcher = Dispatchers.Default,
) = RecyclerViewPagingAdapter(areItemTheSame, areContentsTheSame, mainDispatcher, workerDispatcher)

/**
 * 绑定viewHolder
 */
inline fun <Data : Any?, reified RealData : Data> IRecyclerViewAdapter<Data>.bindHolder(
    noinline block: (inflate: LayoutInflater, parent: ViewGroup, viewType: Int) -> RecyclerViewHolder<RealData, *>
) {
    this.registerData(RealData::class.java, RecyclerView.INVALID_TYPE, block)
}

/**
 * 基于[RecyclerViewHolder]创建一个holder对象，如果满足不了需求，请自己继承[RecyclerViewHolder].
 * 在同一个adapter作用域内，多次注册，找到第一个匹配[RealData],就不会再向下寻找
 */
inline fun <Data : Any?, reified RealData : Data, reified Binding : ViewBinding> IRecyclerViewAdapter<Data>.bindHolder(
    noinline onHolderCreated: (RecyclerViewHolder<RealData, Binding>.() -> Unit)? = null/*holder创建完成监听*/,
    crossinline block: RecyclerViewHolder<RealData, Binding>.(RealData) -> Unit/*绑定holder监听*/
) {
    bindHolder { inflater, parent, viewType ->
        val bindingInstance =
            Binding::class.java.createViewBindingInstance(inflater, parent, false)!!
        val holder = object : RecyclerViewHolder<RealData, Binding>(bindingInstance) {
            override fun bindData(data: RealData) {
                block.invoke(this, data)
            }
        }
        onHolderCreated?.invoke(holder)
        holder
    }
}

/**
 * 通过view绑定
 * 基于[RecyclerViewHolder]创建一个holder对象，如果满足不了需求，请自己继承[RecyclerViewHolder].
 * 在同一个adapter作用域内，多次注册，找到第一个匹配[RealData],就不会再向下寻找
 */
inline fun <Data : Any?, reified RealData : Data> IRecyclerViewAdapter<Data>.bindHolder(
    noinline onHolderView: ((LayoutInflater, ViewGroup) -> View)/*holder创建完成监听*/,
    noinline onHolderCreated: (RecyclerViewHolder<RealData, ViewBinding>.() -> Unit)? = null/*holder创建完成监听*/,
    crossinline block: RecyclerViewHolder<RealData, ViewBinding>.(RealData) -> Unit/*绑定holder监听*/
) {
    bindHolder { inflater, parent, viewType ->
        val view = onHolderView.invoke(inflater, parent)
        val holder = object : RecyclerViewHolder<RealData, ViewBinding>(view) {
            override fun bindData(data: RealData) {
                block.invoke(this, data)
            }
        }
        onHolderCreated?.invoke(holder)
        holder
    }
}

/**
 * 基于[RecyclerViewHolder]创建一个holder对象，如果满足不了需求，请自己继承[RecyclerViewHolder].
 * 在同一个adapter作用域内，多次注册，找到第一个匹配[RealData],就不会再向下寻找
 */
inline fun <Data : Any?, reified RealData : Data> IRecyclerViewAdapter<Data>.recyclerViewHolder(
    noinline onHolderView: ((LayoutInflater, ViewGroup) -> View)/*holder创建完成监听*/,
    crossinline block: RecyclerViewHolder<RealData, ViewBinding>.(RealData) -> Unit/*绑定holder监听*/
) {
    bindHolder(onHolderView, null, block)
}

/**
 * 基于[RecyclerViewHolder]创建一个holder对象，如果满足不了需求，请自己继承[RecyclerViewHolder].
 * 在同一个adapter作用域内，多次注册，找到第一个匹配[RealData],就不会再向下寻找
 */
inline fun <Data : Any?, reified RealData : Data, reified Binding : ViewBinding> IRecyclerViewAdapter<Data>.recyclerViewHolder(
    crossinline block: RecyclerViewHolder<RealData, Binding>.(RealData) -> Unit/*绑定holder监听*/
) {
    bindHolder(null, block)
}


/**
 * 刷新数据
 */
fun <Data> RecyclerViewAdapter<Data>.refreshList(
    newList: List<Data>?,
    isReplaceDatas: Boolean = false/*newList是否替换之前的datas对象*/
) {
    submitList(newList, isReplaceDatas)
}

suspend fun <Data> RecyclerViewAdapter<Data>.refreshListAsync(
    newList: List<Data>?,
    isReplaceDatas: Boolean = false/*newList是否替换之前的datas对象*/
) {
    submitListAsync(newList, isReplaceDatas)
}

/**
 * 刷新数据
 */
fun <Data> RecyclerViewListAdapter<Data>.refreshList(
    newList: List<Data>?,
    commitCallback: Runnable? = null/*内部计算完差异，提交完成的回调*/
) {
    if (commitCallback == null) {
        submitList(newList)
    } else {
        submitList(newList, commitCallback)
    }
}

/**
 * 刷新数据
 */
fun <Data : Any> RecyclerViewPagingAdapter<Data>.refreshList(
    newList: List<Data>?,
    lifecycleOwner: LifecycleOwner,
) {
    submitData(lifecycleOwner.lifecycle, PagingData.from(newList ?: listOf()))
}

/**
 * 讲适配器和数据源绑定
 */
fun <Data : Any, Adapter : RecyclerViewPagingAdapter<Data>> LifecycleOwner.bindPagingAdapter(
    adapter: Adapter,
    pagingData: LiveData<PagingData<Data>>
) {
    pagingData.observe(this) {
        adapter.submitData(this@bindPagingAdapter.lifecycle, it)
    }
}

/**
 * 创建分页livedata
 */
fun <Key : Any, Value : Any> createPagingData(
    config: PagingConfig,
    initialKey: Key? = null,
    pagingSourceFactory: () -> PagingSource<Key, Value>,
): LiveData<PagingData<Value>> {
    return Pager(config, initialKey, pagingSourceFactory).liveData
}

/**
 * 创建分页livedata
 */
fun <Key : Any, Value : Any> createPagingLoadData(
    config: PagingConfig,
    initialKey: Key? = null,
    onRefreshBlock: ((state: PagingState<Key, Value>) -> Key?) = { initialKey },/*刷新的时候回调*/
    onLoadBlock: (params: PagingSource.LoadParams<Key>) -> PagingSource.LoadResult<Key, Value>,/*加载的时候回调*/
): LiveData<PagingData<Value>> {
    return createPagingData(config, initialKey, pagingSourceFactory = {
        object : PagingSource<Key, Value>() {
            override fun getRefreshKey(state: PagingState<Key, Value>): Key? {
                return onRefreshBlock.invoke(state)
            }

            override suspend fun load(params: LoadParams<Key>): LoadResult<Key, Value> {
                return onLoadBlock.invoke(params)
            }
        }
    })
}

/**
 * 通过position找到holder
 */
inline fun <reified Holder : RecyclerViewHolder<*, *>> RecyclerView.findViewHolderForAdapterPosition(
    position: Int
): Holder? {
    return findViewHolderForAdapterPosition(position).asOrNull<Holder>()
}

/**
 * 给线性布局设置分割线
 */
fun RecyclerView.addDividingWithLinearLayoutManager(
    size: Int,
    @ColorInt color: Int,
    radius: Float = 0f,
    orientation: Int = DividerItemDecoration.VERTICAL,
    startMargin: Int = 0,
    endMargin: Int = 0,
    drawLastDivider: Boolean = false,
) {
    val layoutManager = this.layoutManager
    this.addItemDecoration(
        LinearLayoutManagerDivider(
            this.context,
            if (layoutManager is LinearLayoutManager) {
                layoutManager.orientation
            } else {
                orientation
            }
        ).also {
            it.setDrawable(GradientDrawable().also { drawable ->
                drawable.setColor(color)
                drawable.cornerRadius = radius
                drawable.shape = GradientDrawable.RECTANGLE
                if (orientation == DividerItemDecoration.VERTICAL) {
                    drawable.setSize(-1, size)
                } else {
                    drawable.setSize(size, -1)
                }
            })
            it.startMargin = startMargin
            it.endMargin = endMargin
            it.drawLastDivider = drawLastDivider
        })
}

/**
 * 滚动到第一个
 */
fun RecyclerView.scrollToPositionWithOffset(position: Int, offset: Int = 0) {
    when (val manager = layoutManager) {
        is LinearLayoutManager -> {
            manager.scrollToPositionWithOffset(position, offset)
        }
        is GridLayoutManager -> {
            manager.scrollToPositionWithOffset(position, offset)
        }
        is StaggeredGridLayoutManager -> {
            manager.scrollToPositionWithOffset(position, offset)
        }
        else -> scrollToPosition(position)
    }
}

/**
 * 需要一个绑定的数据
 */
fun <T> RecyclerViewHolder<T, *>.requireData(): T {
    return dataWhenBind ?: bindingData ?: throw Exception("no data")
}

/**
 * 设置recyclerView刷新是否有动画效果。可以解决闪屏问题
 */
fun RecyclerView.setSupportsChangeAnimations(supportsChangeAnimations: Boolean) {
    itemAnimator.asOrNull<SimpleItemAnimator>()?.supportsChangeAnimations = supportsChangeAnimations
}